import jwt from "jsonwebtoken";
import {
  UnauthorizedError,
  ForbiddenError,
  BadRequestError,
} from "./../../utils/errors.js";
import Joi from "joi";

/**
 * 认证中间件系统
 */
export class AuthMiddleware {
  /**
   * JWT验证中间件
   * @param {string} secret - JWT密钥
   */
  static authenticate(secret) {
    return (req, res, next) => {
      try {
        // 1. 从Header、Cookie或Query中获取token
        const token = this._extractToken(req);
        // 2. 验证token
        const decoded = this._verifyToken(token, secret);
        console.log("鉴权成功，解码后的token:", decoded);
        // 3. 将用户信息附加到请求对象
        req.user = {
          ...decoded,
          isAdmin: decoded.role === "admin" || decoded.role === "superadmin",
        };

        // 4. 记录认证日志
        console.log(`[Auth] 用户认证成功: ${decoded.id}`);
        if (!decoded.id) {
          throw new UnauthorizedError("未找到用户ID，Token无效");
        }
        next();
      } catch (error) {
        next(error); // 传递给错误处理中间件
      }
    };
  }

  /**
   * 角色检查中间件
   * @param {string[]} allowedRoles - 允许的角色数组
   */
  static authorize(allowedRoles = []) {
    console.log("授权中间件，允许角色:", allowedRoles);
    return (req, res, next) => {
      console.log("授权中间件", req.user.role);
      if (!req.user) {
        throw new UnauthorizedError("用户未认证");
      }

      if (allowedRoles.length > 0 && !allowedRoles.includes(req.user.role)) {
        throw new ForbiddenError("权限不足");
      }

      next();
    };
  }

  /**
   * 请求数据验证中间件
   * @param {Joi.Schema} schema - Joi验证模式
   */
  static validate(schema, options = { skipAuth: false }) {
    return (req, res, next) => {
      console.log("Joi验证模式");
      // 数据验证逻辑（始终执行）
      const { error, value } = schema.validate(
        req.method === "GET" ? req.query : req.body,
        { abortEarly: false }
      );
      if (error) {
        const details = error.details.map((d) => d.message);
        throw new BadRequestError("数据验证失败", { details });
      }
      console.log("验证通过", value);
      req.validatedData = value;

      // 根据配置决定是否跳过 Token 检查
      if (options.skipAuth) {
        console.log("跳过 Token 检查");
        return next(); // 跳过 Token 检查
      }

      // 需要 Token 的接口继续验证
      const token =
        req.headers.authorization?.replace("Bearer ", "") || req.body?.token;
      console.log("前端接收的token", token);
      if (!token) {
        throw new BadRequestError("请提供有效的 Token");
      }

      next();
    };
  }

  /**
   *
   */
  static verifyToken() {
    return (req, res, next) => {
      // 返回中间件函数
      const token = req.headers.authorization?.split(" ")[1];
      if (!token) {
        return res.status(401).json({ valid: false, error: "MISSING_TOKEN" });
      }

      try {
        const payload = jwt.verify(token, process.env.JWT_SECRET);
        if (payload.role !== "admin" && payload.role !== "superadmin") {
          return res
            .status(403)
            .json({ valid: false, error: "INSUFFICIENT_PERMISSIONS" });
        }

        req.user = {
          id: payload.id,
          role: payload.role,
        };
        next();
      } catch (err) {
        console.log("验证失败：", err);
        return res.status(401).json({ valid: false, error: "INVALID_TOKEN" });
      }
    };
  }
  /**
   * 数据验证中间件（纯数据验证，不涉及认证）
   * 验证批量删除用户的id集合
   */
  static validatePure(schema) {
    console.log("数据验证中间件");
    return (req, res, next) => {
      const { error, value } = schema.validate(
        req.method === "GET" ? req.query : req.body,
        { abortEarly: false }
      );
      if (error) {
        const details = error.details.map((d) => ({
          field: d.path.join("."),
          message: d.message.replace(/"/g, ""),
        }));
        throw new BadRequestError("数据验证失败", { details });
      }

      req.validatedData = value;
      next();
    };
  }

  // 私有方法：从请求中提取token
  static _extractToken(req) {
    const authHeader = req.headers["authorization"];
    if (authHeader && authHeader.startsWith("Bearer ")) {
      return authHeader.substring(7);
    }
    // 2. 从请求体中获取（兼容前端传参）
    if (req.body?.refreshToken) {
      return req.body.refreshToken;
    }
    if (req.cookies?.token) {
      return req.cookies.token;
    }

    if (req.query.token) {
      return req.query.token;
    }

    throw new UnauthorizedError("未提供认证令牌");
  }

  // 私有方法：验证token
  static _verifyToken(token, secret) {
    console.log("JWT_SECRET--", token);
    try {
      return jwt.verify(token, secret);
    } catch (error) {
      console.error("[Auth] Token验证失败:", error);
      throw new UnauthorizedError("无效的认证令牌");
    }
  }
}
